#ifndef THREADPOOL_H
#define THREADPOOL_H

#include <vector>
#include <memory>
#include <atomic>
#include <mutex>
#include <queue>
#include <condition_variable>
#include "Thread.hpp"
#include "Task.hpp"
#include <unordered_map>

using namespace std;

enum class poolMode {
	POOL_FIXED,//fixed mode based on the cpu cores;
	POOL_CACHED//flexible mode dynamic increment
};


class threadPool
{
public:
	threadPool();
	~threadPool();
	//set the working mode of the thread pool
	void setMode(poolMode mode) { 
		if (checkRunningState())return;
		mode_ = mode; }
	//start the thread pool
	void start(int size=4);
	//set the working taskqueue threshhold
	void setTaskQueThreshHold(int threshhold) { taskQueMaxThreshHold_ = threshhold; }

	void setThreadThreshHold(int threshhold) {
		if (checkRunningState())return;
		if (mode_ == poolMode::POOL_FIXED) {
			threadMaxThreshHold_ = threshhold;
		}
	}
	//submit the task
	Result submitTask(shared_ptr<Task> task);

	void threadFunc(int );

	threadPool(const threadPool& cp) = delete;
	threadPool& operator=(const threadPool& cp) = delete;

private:
	bool checkRunningState() {
		return isPoolRunning_;
	}

	//vector<unique_ptr<Thread>> threads_;
	unordered_map<int, unique_ptr<Thread>> threads_;
	int initThreadSize_;
	std::atomic_int idleThreadNum_;
	int threadMaxThreshHold_;
	std::atomic_int curThreadNum_;

	queue<shared_ptr<Task>> taskQue_;
	atomic_int taskSize_;
	int taskQueMaxThreshHold_;
	mutex taskQueMtx_;
	
	condition_variable notEmpty_;
	condition_variable notFull_;
	condition_variable exit_;

	poolMode mode_;

	std::atomic_bool isPoolRunning_;
};

#endif